package edu.gatech.spacetraderteam3.view;

import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;

/**
 * Represents the spinners components in the GUI
 * @author Alexander Ikonomidis
 * @version 1.0
 */
public class SGGSpinner extends SGGComponent {

    /**
     * The min, max, and current value of the spinner
     */
    private int min, max, value;

    /**
     * The image displayed behind the text
     */
    private final BufferedImage text;

    /**
     * The plus and minus buttons
     */
    private final SGGButton plus, minus;

    /**
     * The text field that holds the current data
     */
    private final SGGTextField data;

    /**
     * Constructor. Sets Minimum, Maximum and starting value. 
     * @param min Minimum Value
     * @param max Maximum Value
     * @param initValue Initial value
     */
    protected SGGSpinner(int min, int max, int initValue) {
        super(120, 31);
        this.min = min;
        this.max = max;
        this.value = initValue;
        plus = new SGGButton(Assets.ButtonType.SPINNER_GREY_PLUS);
        data = new SGGTextField("" + value);
        data.showBox(false);
        minus = new SGGButton(Assets.ButtonType.SPINNER_GREY_MINUS);
        text = Assets.MiscImage.SPINNER_BLUE_TEXT_AREA.image();

        data.setAcceptLetters(false);
        data.setMaximumLength(3);
    }

    /**
     * Paints the Spinner
     * @param g Graphics component to paint on
     */
    public void doPaint(Graphics2D g) {
        minus.setOrigin(getX(), getY());
        data.setOrigin(getX() + minus.getWidth() + 10, getY() + 5);
        plus.setOrigin(getX() + minus.getWidth() + text.getWidth(), getY());

        plus.paint(g);
        g.drawImage(text, getX() + plus.getWidth(), getY(), null);
        data.paint(g);
        minus.paint(g);
    }

    /**
     * Checks to see if plus or minus buttons are clicked
     * @param p - Point that was clicked
     */
    protected void doClick(Point p) {
        if (plus.contains(p)) {
            plus.doClick(p);
        } else if (minus.contains(p)) {
            minus.doClick(p);
        }
    }

    /**
     * Sets spinner value based on number key presses
     * @param k Key that was pressed. 
     */
    protected void doKey(KeyEvent k) { // Depends on the fact that the spinner accepts only numbers.
        data.doKey(k);
        if (data.getText().length() > 0) {
            try {
                setValue(Integer.parseInt(data.getText()));
            } catch (NumberFormatException nfe) { // $codepro.audit.disable logExceptions
                setValue(0);
            }
        }
    }

    /**
     * If plus button was pressed, increments by one. If minus button was pressed, decrements by one. 
     */
    protected void doRelease() {
        if (plus.isPressed()) {
            plus.doRelease();
            setValue(value + 1);
            sggEventListener.doEvent(new SGGEvent("Spinner value increased.", this));
        } else if (minus.isPressed()) {
            minus.doRelease();
            setValue(value - 1);
            sggEventListener.doEvent(new SGGEvent("Spinner value decreased.", this));
        }
    }

    /**
     * Does stuff when it loses focus
     */
    protected void loseFocus() {
        if (data.getText().length() == 0) {
            setValue(0);
        }
    }

    /**
     * Gets the current spinner value
     * @return The spinner value
     */
    public int getValue() {
        return value;
    }

    /**
     * Sets the spinner value
     * @param value Value to set the spinner
     */
    public void setValue(int value) {
        this.value = Math.min(max, Math.max(min, value));
        data.setText("" + this.value);
        sggEventListener.doEvent(new SGGEvent("Spinner value entered.", this));
    }

    /**
     * Gets the minimum spinner value
     * @return Minimum spinner value
     */
    public int getMin() {
        return min;
    }

    /**
     * Sets minimum spinner value
     * @param min Minimum spinner value to set
     */
    public void setMin(int min) {
        this.min = min;
        if (value < min) {
            value = min;
        }
    }

    /**
     * Getter for maximum spinner value
     * @return Maximum spinner value
     */
    public int getMax() {
        return max;
    }

    /**
     * Setter for maximum spinner value
     * @param max Maximum spinner value
     */
    public void setMax(int max) {
        this.max = max;
        if (value > max) {
            value = max;
        }
    }

    /**
     * @return the current value in string form
     */
    public String toString() {
        return "" + value;
    }
}
